/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051，12MHz
  日    期: 2011-8-9
*/

#include "i2c.h"

void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}
//总线启动条件
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;    //SCL高电平期间，被拉SDA低电平
    IIC_Delay(DELAY_TIME);
    SCL = 0;	//再拉低SCL
}

//总线停止条件
void IIC_Stop(void)
{
    SDA = 0;	//保证高电平
		SCL = 1;	//SCL高电平期间 SDA被拉高
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答
void IIC_SendAck(bit ackbit)
{
    SCL = 0;        //时钟线拉低
    SDA = ackbit;  	// 0：应答，1：非应答
    IIC_Delay(DELAY_TIME);
    SCL = 1;				//时钟线拉高，读取数据
    IIC_Delay(DELAY_TIME);
    SCL = 0; 					//时钟线拉低
    SDA = 1;					
    IIC_Delay(DELAY_TIME);
}

//等待应答
bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;    //时钟线拉高
    IIC_Delay(DELAY_TIME);
    ackbit = SDA; //读取数据，0：应答，1：非应答
    SCL = 0;		//时钟线拉低
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;//拉低时钟线，开始写
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;//读取数据，1拉高
        else SDA  = 0;					//读取数据，0拉高
        IIC_Delay(DELAY_TIME);
        SCL = 1;//拉高写入数据
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
  unsigned char i, da;
	for(i=0; i<8; i++)
	{   
		SCL = 1;//时钟线拉高，开始读取
		IIC_Delay(DELAY_TIME);
		da <<= 1;
		if(SDA) da |= 1;
		SCL = 0;
		IIC_Delay(DELAY_TIME);
   }
    return da;    
}
/************************************************************************************
**函数功能：ad读电压,模数转换
**参    数：addr：输入的地址，滑动变阻器：0x43,光敏电阻:0x41
**返回值  ：读到的电压
*********************************************************************************/
unsigned int ad_read(unsigned int addr)
{
	unsigned int temp;//临时变量
	
	IIC_Start();//开始初始化
	/*开始写*/
	IIC_SendByte(0x90);//开始写的地址
	IIC_WaitAck();//等待应答
	/*写的位置*/
	IIC_SendByte(addr);//选择需要读取的模块，滑动变阻器：0x43,光敏电阻:0x41
	IIC_WaitAck();//等待应答
	
	IIC_Start();//开始初始化
	/*开始读*/
	IIC_SendByte(0x91);//开始读的地址
	IIC_WaitAck();//等待应答
	
	temp=IIC_RecByte();//开始读
	IIC_SendAck(1);//发生非应答，只读一次不读取了
	IIC_Stop();//停止
	return temp;
}
/************************************************************************************
**函数功能：da写入数据,数模转换
**参    数：dat：写入的数据
**返回值  ：无
*********************************************************************************/
void da_write(unsigned int dat)
{
	IIC_Start();//开始
	IIC_SendByte(0x90);//开始写的地址
	IIC_WaitAck();//等待应答
	
	IIC_SendByte(0x41);//允许da输出，保证d6=1即可
	IIC_WaitAck();//等待应答
	
	IIC_SendByte(dat);//写入的数据
	IIC_WaitAck();//等待应答
	IIC_Stop();//停止
}